[Xamarin.Forms] Firebase Analyticsを導入してみたので、手順をまとめた! (Android & iOS)
2019年10月31日に「AndroidとiOS向けのGoogle Analytics」のサポートが終了します。
というわけで、移行する前準備として、XamarinでFirebase Analyticsを試してみました。
- Q:なぜXamarin?
- A:趣味です!
Firebase Analyticsのイベントについては、下記をどうぞ!
目次
環境
- Windows
- Windows 10 Pro
- Visual Studio Community 2019 (Ver16.1.5)
- macOS
- macOS Mojave 10.14.5
- Visutal Studio Community 2019 for Mac (Ver8.1.3)
- Xcode 10.2.1
- Android
- Pixel 3a (Android 9)
- iOS Simulator
- iPhone Xs 12.2
- Xamarin
- Xamarin Ver16.1.0.545
- Xamarin.Android SDK Ver9.3.0.23
- Xamarin.iOS and Xamarin.Mac SDK Ver12.10.0.157
- Library
- Xamarin.Forms Ver4.0.0.425677
- Xamarin.Firebase.Analytics Ver60.1142.1
- Xamarin.Firebase.iOS.Analytics Ver5.5.0
アプリの新規作成
Visual Studioを起動し、「モバイルアプリ(Xamarin.Forms)」を選択します。
プロジェクト名を適当に入力します。
場所はできるだけ浅い階層にしましょう!(Windowsの場合)
「ソリューションとプロジェクトを同じディレクトリに配置する」にもチェックを入れておきます。
※Windwosでフォルダ/ファイル階層が深いと、Androidのビルドに失敗するためです。
テンプレートは何でも良いですが、シンプルな「空白」を選択しておきます。
Firebaseプロジェクトの作成
Firebase Consoleにアクセスし、「プロジェクトの作成」を選択します。
プロジェクト名を適当に入力し、アナリティクスの地域を日本にします。
Androidアプリ
FirebaseプロジェクトにAndroidアプリを追加
Firebaseプロジェクトで、Androidマークを選択します。
Androidアプリのパッケージ名をコピペ入力し、「アプリを登録」を選択します。
google-services.json
をダウンロードし、「次へ」を選択します。
Firebase SDKの追加は無視して進み、インストールを確認する画面を表示しておきます。
AndroidアプリのFirebase対応
NuGetパッケージのXamarin.Firebase.Analytics
をAndroidプロジェクトにインストールします。
Visual StudioのAndroidプロジェクト直下に、ダウンロードしたgoogle-services.json
を配置します。
続いて、google-services.json
のビルドアクションをGoogleServicesJson
にします。
この項目が存在しない場合は、Visual Studioを再起動したり、ソリューションのリビルドをすれば現れます。
MainActivity.cs
に初期化とイベント送信をお試し実装します。
ハイライト部分が追加したコードです。
using System; using Android.App; using Android.Content.PM; using Android.Runtime; using Android.Views; using Android.Widget; using Android.OS; using Firebase.Analytics; namespace FASample.Droid { [Activity(Label = "FASample", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; var analytics = FirebaseAnalytics.GetInstance(this); base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); LoadApplication(new App()); var bundle = new Bundle(); bundle.PutString(FirebaseAnalytics.Param.ItemCategory, "Monday"); bundle.PutString(FirebaseAnalytics.Param.ItemName, "21:54"); analytics.LogEvent(FirebaseAnalytics.Event.SelectContent, bundle); } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) { Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } } }
動作確認(Android)
それでは、アプリを実行しましょう!!
うまくいけば、10~60秒後ぐらいに「正常に追加されました」と表示されます!
Dashboardでも1ユーザと認識されています。
DebugViewの設定(Android)
こちらを参考に実施します。
数分待つと、DebugViewにいろいろと表示されます!!
出ない場合は、アプリを再起動させればOKでした。
iOSアプリ
FirebaseプロジェクトにAndroidアプリを追加
Firebaseプロジェクトで、「アプリを追加」からiOSマークを選択します。
iOSアプリのバンドルIDをコピペ入力し、「アプリを登録」を選択します。 (実機で動作確認する場合は、実機インストール可能なバンドルIDを使用してください)
GoogleService-Info.plist
をダウンロードし、「次へ」を選択します。
Firebase SDKの追加は無視して進み、インストールを確認する画面を表示しておきます。
iOSアプリのFirebase対応
NuGetパッケージのXamarin.Firebase.iOS.Analytics
をiOSプロジェクトにインストールします。
Visual StudioのiOSプロジェクト直下に、ダウンロードしたGoogleService-Info.plist
を配置します。
続いて、GoogleService-Info.plist
のビルドアクションをBundleResource
にします。
GoogleService-Info.plist
のIS_ANALYTICS_ENABLED
をTrue
に変更します。
<key>IS_ANALYTICS_ENABLED</key> <true></true>
AppDelegate.cs
に初期化とイベント送信をお試し実装します。
ハイライト部分が追加したコードです。
using System; using System.Collections.Generic; using System.Linq; using Foundation; using UIKit; using Firebase.Analytics; namespace FASample.iOS { [Register("AppDelegate")] public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { public override bool FinishedLaunching(UIApplication app, NSDictionary options) { // https://github.com/xamarin/GoogleApisForiOSComponents/issues/158#issuecomment-483194061 var foo = Firebase.Core.Configuration.SharedInstance; Firebase.Core.App.Configure(); global::Xamarin.Forms.Forms.Init(); LoadApplication(new App()); var events = new Dictionary<string, string> { { ParameterNamesConstants.ItemCategory, "Friday" }, { ParameterNamesConstants.ItemName, "17:08" }, }; var sendParams = NSDictionary<NSString, NSObject>.FromObjectsAndKeys( events.Values.ToArray(), events.Keys.ToArray() ); Analytics.LogEvent(EventNamesConstants.SelectContent, sendParams); return base.FinishedLaunching(app, options); } } }
なお、ビルドした際に下記エラーが発生したため、var foo = Firebase.Core.Configuration.SharedInstance;
を追加してます。
error MT5210: Native linking failed, undefined symbol: ... error MT5211: Native linking failed, undefined Objective-C class: ... error MT5201: Native linking failed. Please review the build log and the user flags provided to gcc: -ObjC -ObjC -lc++ -lsqlite3 -lz -ObjC -lc++ -lsqlite3 -lz error MT5202: Native linking failed. Please review the build log.
動作確認(iOS)
それでは、アプリを実行しましょう!!
うまくいけば、10~60秒後ぐらいに「正常に追加されました」と表示されます!
Dashboardでも1ユーザと認識されています。
DebugViewの設定(iOS)
こちらとこちらを参考に--argument=-FIRDebugEnabled
を追加します。
数分待つと、DebugViewにいろいろと表示されます!!
出ない場合は、アプリを再起動させればOKでした。
共通プロジェクトからイベント送信してみる(Xamarin.Forms)
せっかくなので、Xamarin.FormsのDependencyServiceを利用し、共通プロジェクトから呼び出しましょう。
参考にどうぞ!(どちらかというと、これが本命だったりします)
インターフェースを定義
共通プロジェクト(FASample)にIAnalytics.cs
を作成します。
using System.Collections.Generic; namespace FASample { public interface IAnalytics { void LogEvent(string eventName, Dictionary<string, object> eventParams); void Screen(string screenName); } }
Androidの実装
Androidプロジェクト(FASample.Android)にAnalyticsSingleton.cs
とAnalytics_Android.cs
を作成します。
using Android.App; using Firebase.Analytics; namespace FASample.Droid { public class AnalyticsSingleton { public static AnalyticsSingleton GetInstance { get; } = new AnalyticsSingleton(); public FirebaseAnalytics Analytics { get; set; } public Activity Activity { get; set; } private AnalyticsSingleton() { } } }
using System.Collections.Generic; using Android.OS; using Xamarin.Forms; using FASample.Droid; [assembly: Dependency(typeof(Analytics_Android))] namespace FASample.Droid { public class Analytics_Android : IAnalytics { public void LogEvent(string eventName, Dictionary<string, object> eventParams) { if (eventName == null || eventParams == null) return; var analytics = AnalyticsSingleton.GetInstance.Analytics; var bundle = new Bundle(); foreach (var eventParam in eventParams) { if (eventParam.Value.GetType() == typeof(string)) { bundle.PutString(eventParam.Key, (string)eventParam.Value); } if (eventParam.Value.GetType() == typeof(int)) { bundle.PutInt(eventParam.Key, (int)eventParam.Value); } } analytics.LogEvent(eventName, bundle); } public void Screen(string screenName) { if (screenName == null) return; var analytics = AnalyticsSingleton.GetInstance.Analytics; var activity = AnalyticsSingleton.GetInstance.Activity; analytics.SetCurrentScreen(activity, screenName, null); } } }
続いて、MainActivity.cs
のOnCreate()
を次のようにし、FirebaseAnalyticsのインスタンスを保存します。
protected override void OnCreate(Bundle savedInstanceState) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; AnalyticsSingleton.GetInstance.Analytics = FirebaseAnalytics.GetInstance(this); AnalyticsSingleton.GetInstance.Activity = this; base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); LoadApplication(new App()); }
iOSの実装
iOSプロジェクト(FASample.iOS)にAnalytics_iOS.cs
を作成します。
using System.Collections.Generic; using System.Linq; using Foundation; using Firebase.Analytics; using Xamarin.Forms; using FASample.iOS; [assembly: Dependency(typeof(Analytics_iOS))] namespace FASample.iOS { public class Analytics_iOS : IAnalytics { public void LogEvent(string eventName, Dictionary<string, object> eventParams) { if (eventName == null || eventParams == null) return; var sendParams = NSDictionary<NSString, NSObject>.FromObjectsAndKeys( eventParams.Values.ToArray(), eventParams.Keys.ToArray() ); Analytics.LogEvent(eventName, sendParams); } public void Screen(string screenName) { Analytics.SetScreenNameAndClass(screenName, null); } } }
呼び出し側の実装
画面表示時に画面情報を送信し、ボタンを押したときにイベントを送信してみます。
MainPage.xaml
とMainPage.xaml.cs
を編集します。
title="MainPage.xaml"] <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="FASample.MainPage"> <StackLayout VerticalOptions="Center"> <Label Text="Welcome to Xamarin.Forms!" HorizontalOptions="Center" VerticalOptions="Center"/> <Button Text="send event" HorizontalOptions="Center" VerticalOptions="Center" Clicked="Button_OnClicked" /> </StackLayout> </ContentPage>
using System; using System.Collections.Generic; using System.ComponentModel; using Xamarin.Forms; namespace FASample { [DesignTimeVisible(false)] public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } protected override void OnAppearing() { DependencyService.Get<IAnalytics>().Screen("This is MainPage!!!"); base.OnAppearing(); } private void Button_OnClicked(object sender, EventArgs e) { var events = new Dictionary<string, object> { { "item_category", "August" }, { "item_name", "18th" }, { "item_id", 18 } }; DependencyService.Get<IAnalytics>().LogEvent("select_content", events); } } }
いざ、実行します!!
動作確認(Android)
screen_view
が飛んできました。
詳細を見ると、This is MainPage!!!
が表示されています!!
続いて、アプリ画面のボタンを押すと、select_content
が飛んできました。
詳細を確認すると、バッチリ送信できています!!
動作確認(iOS)
iOSも同様です!!
さいごに
結果的には、意外と簡単にできました。(ハマりまくりましたけど……)
やり方は分かったので、あとは本番アプリに適用するだけです。(これが大変だけど……)
参考
- Firebase Analyticsの仕様的な
- Firebase AnalyticsのAndroid的な
- Firebase AnalyticsのiOS的な
- Xamarin